﻿// <copyright project="Salient.SqlServer.NHibernate" file="XDocumentUserType.cs" company="Sky Sanders">
// This source is a Public Domain Dedication.
// Please see http://spikes.codeplex.com/ for details.   
// Attribution is appreciated
// </copyright> 
// <version>1.0</version>
using System;
using System.Data;
using System.Data.Common;
using System.Xml.Linq;
using NHibernate.SqlTypes;
using NHibernate.UserTypes;

namespace Salient.SqlServer.NHibernate
{
    /// <summary>
    /// started with tobin's found class http://gist.github.com/47082
    /// 
    /// XDocument PrettyPrints anything it parses. Perhaps should add LoadOptions to prevent
    /// modification of original content?
    /// </summary>
    public class XDocumentUserType : IUserType
    {
        #region IUserType Members

        public new bool Equals(object x, object y)
        {
            if (x == null || y == null)
                return false;

            var xdoc_x = (XDocument) x;
            var xdoc_y = (XDocument) y;
            return xdoc_y.ToString() == xdoc_x.ToString();
        }

        public int GetHashCode(object x)
        {
            return x.GetHashCode();
        }


        public object NullSafeGet(IDataReader rs, string[] names, object owner)
        {
            if (names.Length != 1)
                throw new InvalidOperationException("names array has more than one element. can't handle this!");


            var val = rs[names[0]] as string;

            if (val != null)
            {
                return XDocument.Parse(val);
            }

            return null;
        }

        public void NullSafeSet(IDbCommand cmd, object value, int index)
        {
            var parameter = (DbParameter) cmd.Parameters[index];

            if (value == null)
            {
                parameter.Value = DBNull.Value;
                return;
            }

            parameter.Value = value.ToString();
        }

        public object DeepCopy(object value)
        {
            var toCopy = value as XDocument;

            if (toCopy == null)
                return null;

            XDocument copy = XDocument.Parse(toCopy.ToString());

            return copy;
        }

        public object Replace(object original, object target, object owner)
        {
            throw new NotImplementedException();
        }

        public object Assemble(object cached, object owner)
        {
            var str = cached as string;
            if (str != null)
            {
                return XDocument.Parse(str);
            }
            else
            {
                return null;
            }
        }

        public object Disassemble(object value)
        {
            var val = value as XDocument;
            if (val != null)
            {
                return val.ToString();
            }
            else
            {
                return null;
            }
        }

        public SqlType[] SqlTypes
        {
            get { return new SqlType[] {new SqlXmlStringType()}; }
        }

        public Type ReturnedType
        {
            get { return typeof (XDocument); }
        }

        public bool IsMutable
        {
            get { return true; }
        }

        #endregion
    }
}